package lexer

import (
	"fmt"
	"goc/utils"
	"strconv"
	"unicode"
)

type Lexer struct {
	input *string
}

// 创建一个新的Lexer对象，参数为输入的字符串
func NewLexer(input *string) *Lexer {
	// 创建一个新的Lexer对象，并将输入的字符串赋值给对象的input字段
	l := &Lexer{input: input}
	// 返回创建的Lexer对象
	return l
}

func (lex *Lexer) Tokenize() *Token {
	Head := &Token{}
	Cur := Head
	pos := 0

	for pos < len(*lex.input) {
		if unicode.IsSpace(rune((*lex.input)[pos])) {
			pos++
			continue
		}

		if unicode.IsDigit(rune((*lex.input)[pos])) {
			// 数字
			start := pos
			for pos < len(*lex.input) && unicode.IsDigit(rune((*lex.input)[pos])) {
				pos++
			}
			val, _ := strconv.Atoi((*lex.input)[start:pos])
			Cur.Next = newToken(TK_NUM, (*lex.input)[start:pos], pos-start)
			//移动指针到下一个词法单元,Next是指针类型(Next存的是一个地址)，指向下一个Token
			Cur = Cur.Next
			Cur.Val = val
			continue
		} else if string((*lex.input)[pos]) == "+" || string((*lex.input)[pos]) == "-" {
			// 解析操作符
			// 操作符长度都为1
			Cur.Next = newToken(TK_PUNCT, (*lex.input)[pos:pos+1], 1)
			Cur = Cur.Next
			pos++
			continue
		}
		// 处理无法识别的字符
		utils.Fatal("invalid token:" + string((*lex.input)[pos]))
	}
	// 解析结束，增加一个EOF，表示终止符。
	Cur.Next = newToken(TK_EOF, "", 0)
	// Head无内容，所以直接返回Next
	return Head.Next
}

// 生成新的Token
func newToken(Kind Tag, loc string, length int) *Token {
	return &Token{Kind: Kind, Loc: loc, Len: length}
}

// 跳过所有空白符如：空格、回车
func (lex *Lexer) isspace(ch int32) bool {
	if ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r' {
		return true
	}
	return false
}

// 判断是不是数字
func (lex *Lexer) isDigit(ch int32) bool {
	//46表示小数点
	return '0' <= ch && ch <= '9' || ch == 46
}

// 判断Tok的值是否等于指定值，没有用char，是为了后续拓展
func (lex *Lexer) Equal(Tok *Token, Str string) bool {
	/* fmt.Println("kind:", Tok.Kind)
	fmt.Println("TK_PUNCT:", TK_PUNCT) */
	fmt.Println(Tok.Kind == TK_PUNCT)
	return Tok.Kind == TK_PUNCT
}

// equal 函数用于判断 Token 的值是否等于指定字符串
/* func (lex *Lexer) Equal(tok *Token, str string) bool {
	strBytes := []byte(str)
	// 先比较前 Tok.Len 个字节是否相同
	if tok.Len > len(strBytes) || !bytes.Equal(tok.Loc[:tok.Len], strBytes[:tok.Len]) {
		return false
	}
	// 再确保 str 的长度刚好等于 Tok.Len
	return len(strBytes) == tok.Len
} */

// 跳过指定的Str
func (lex *Lexer) Skip(Tok *Token, Str string) *Token {
	if !lex.Equal(Tok, Str) {
		// utils.Fatal(Str)
		return Tok.Next
	}
	return Tok.Next
}

// 返回TK_NUM的值
/* func getNumber(Tok *Token) int {
	if Tok.Kind != TK_NUM {
		utils.Fatal("expect a number")
	}
	return Tok.Val
} */
/* func getNextNumber(tok *Token) *Token {
	for tok != nil && tok.Kind != TK_NUM {
		tok = tok.Next
	}
	return tok
} */

func getNextNumber(tok *Token) int {
	if tok.Kind == TK_NUM {
		return tok.Val
	}
	return 0
}

// 打印Token链表（用于测试）
func (lex *Lexer) PrintTokens(tok *Token) {
	for tok.Kind != TK_EOF {
		var kind string
		/* switch tok.Kind {
		case TK_PUNCT:
			kind = "PUNCT"
		case TK_NUM:
			kind = "NUM"
		case TK_EOF:
			kind = "EOF"
		} */
		if tok.Kind == TK_PUNCT {
			kind = "PUNCT"
		}
		if tok.Kind == TK_NUM {
			kind = "NUM"
		}
		if tok.Kind == TK_EOF {
			kind = "EOF"
		}
		fmt.Printf("Kind: %-5s Loc: %-5q Len: %d Val: %d\n",
			kind, tok.Loc, tok.Len, tok.Val)
		tok = tok.Next
	}
}
